#include<iostream>
#include"ContactException.h"
#include"add_contacts.pb.h"
#include"httplib.h"

using namespace std;
using namespace httplib;

void addContacts(const std::string& server_ip, const std::string& server_port);
void buildReqestContact(add_contacts::RequestContacts* req);


void menu()
{
    std::cout << "-----------------------------------------------------" << std::endl
    << "--------------- 请选择对通讯录的操作 ----------------" << std::endl
     << "------------------ 1、新增联系⼈ --------------------" << std::endl
     << "------------------ 2、删除联系⼈ --------------------" << std::endl
     << "------------------ 3、查看联系⼈列表 ----------------" << std::endl
     << "------------------ 4、查看联系⼈详细信息 ------------" << std::endl
     << "------------------ 0、退出 --------------------------" << std::endl
     << "-----------------------------------------------------" << std::endl;

}

int main(int argc, char* argv[])
{
    if(argc != 3)
    {
        cout << "Usage: " << argv[0] << " <server_ip> <server_port>" << endl;
        return 1;
    }

    enum OPTION {EXIT = 0, ADD, DEL, FIND_ALL, FIND_ONE};
    while(true)
    {
        menu();
        cout << "请输入选项：";
        int choice;
        cin >> choice;
        cin.ignore(256,'\n');
        try
        {
            switch(choice)
            {
                case OPTION::EXIT:
                    cout << "退出程序" << endl;
                    return 0;
                case OPTION::ADD:
                    addContacts(argv[1], argv[2]);
                    break;
                case OPTION::DEL:
                case OPTION::FIND_ALL:
                case OPTION::FIND_ONE:
                    break;
                default:
                    cout << "输入error，请重新输入" << endl;
                    break;
            }
        }catch(const ContactException& e)
        {
            std::cerr << "---> 操作通讯录时发现异常！！！" << std::endl
                        << "---> 异常信息：" << e.what() << std::endl;
        }
    }
    return 0;
}

void buildReqestContact(add_contacts::RequestContacts* req)
{
    cout << "-------------新增联系⼈-------------" << endl;
    cout << "请输入联系⼈的姓名：";
    string name;
    getline(cin, name);
    req->set_name(name);

    cout << "请输入联系⼈年龄：";
    int age;
    cin >> age;
    req->set_age(age);
    //前面用了 cin >> age; 读取一个整数后，用户输入时最后按下的回车键（\n）仍然留在输入缓冲区。
    //如果不清理掉这个残留的换行符，下一次使用 getline(cin, str) 等读取整行字符串的操作时，会直接读到这个换行符，导致读取失败或行为异常。
    //丢弃（忽略）输入缓冲区中最多 256 个字符，直到遇到换行符 '\n' 为止。
    cin.ignore(256, '\n');

    for(int i = 0; ;i++)
    {
        cout << "请输入联系⼈的电话号码 " << i+1 << "(输入回车退出): ";
        string number;
        getline(cin, number);
        if(number.empty()) break;
        add_contacts::RequestContacts_Phone* phone = req->add_phone_numbers();
        phone->set_number(number);
        cout << "请输入联系⼈的电话类型" << "(1:移动 2:固定): ";
        int type;
        cin >> type;
        cin.ignore(256, '\n');
        switch (type) 
        {
            case 1:
                phone->set_type(add_contacts::RequestContacts_Phone_PhoneType_M_P);
                break;
            case 2:
                phone->set_type(add_contacts::RequestContacts_Phone_PhoneType_TEL_P);
                break;
            default:
                cout << "输入错误" << endl;
                break;
        }
    }
}

void addContacts(const std::string& server_ip, const std::string& server_port)
{
    Client cli(server_ip, stoi(server_port));
    
    //构造req
    add_contacts::RequestContacts req;
    buildReqestContact(&req);

    //序列化req
    string req_str;
    if(!req.SerializeToString(&req_str))
    {
        throw ContactException("序列化请求失败！");
    }
    
    //发送post请求到服务器
    auto res = cli.Post("/add_contacts", req_str, "application/protobuf");
    if(!res)
    {
        std::string err_desc;
        err_desc.append("/contacts/del 链接错误！错误信息：")
           .append(httplib::to_string(res.error()));
        throw ContactException(err_desc);
    }

    //反序列化resp
    add_contacts::ResponseContacts resp;
    bool parse = resp.ParseFromString(res->body);

    if(res->status != 200 && !parse)
    {
        std::string err_desc;
        err_desc.append("/contacts/del 调用失败")
           .append(std::to_string(res->status))
           .append("(").append(res->reason).append(")");
        throw ContactException(err_desc);
    }
    else if(res->status != 200)
    {
        std::string err_desc;
        err_desc.append("/contacts/del 调用失败")
           .append(std::to_string(res->status))
           .append("(").append(res->reason).append(") 错误原因:")
           .append(resp.errmessage());
        throw ContactException(err_desc);
    }
    else if(!resp.success())
    {
        std::string err_desc;
        err_desc.append("/contacts/del 结果异常，异常原因：")
           .append(resp.errmessage());
        throw ContactException(err_desc);
    }

    //打印resp结果
    cout << "添加联系人成功！联系人ID：" << resp.uid() << endl;
}